home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / ATL / include / wceatl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  34.7 KB  |  1,388 lines

  1. // This is a part of the Active Template Library(Windows CE)
  2. // Copyright (C) 1996-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef _ATL_DLL
  12.  
  13. namespace ATL
  14. {
  15. // ATLAPI Atl...() are moved here from atlcom.h in order to prevent multiple compilation
  16. #ifndef _ATL_DLL
  17. ATLAPI AtlIPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk)
  18. {
  19.     ATLASSERT(pMap != NULL);
  20.     HRESULT hr = S_OK;
  21.     DWORD dwVer;
  22.     hr = pStm->Read(&dwVer, sizeof(DWORD), NULL);
  23.     if (FAILED(hr))
  24.         return hr;
  25.     if (dwVer > _ATL_VER)
  26.         return E_FAIL;
  27.  
  28.     CComPtr<IDispatch> pDispatch;
  29.     const IID* piidOld = NULL;
  30.     for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  31.     {
  32.         if (pMap[i].szDesc == NULL)
  33.             continue;
  34.  
  35.         // check if raw data entry
  36.         if (pMap[i].dwSizeData != 0)
  37.         {
  38.             void* pData = (void*) (pMap[i].dwOffsetData + (DWORD)pThis);
  39.             hr = pStm->Read(pData, pMap[i].dwSizeData, NULL);
  40.             if (FAILED(hr))
  41.                 return hr;
  42.             continue;
  43.         }
  44.  
  45.         CComVariant var;
  46.  
  47.         hr = var.ReadFromStream(pStm);
  48.         if (FAILED(hr))
  49.             break;
  50.  
  51.         if (pMap[i].piidDispatch != piidOld)
  52.         {
  53.             pDispatch.Release();
  54.             if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  55.             {
  56.                 ATLTRACE2(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  57.                 hr = E_FAIL;
  58.                 break;
  59.             }
  60.             piidOld = pMap[i].piidDispatch;
  61.         }
  62.  
  63.         if (FAILED(CComDispatchDriver::PutProperty(pDispatch, pMap[i].dispid, &var)))
  64.         {
  65.             ATLTRACE2(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  66.             hr = E_FAIL;
  67.             break;
  68.         }
  69.     }
  70.     return hr;
  71. }
  72.  
  73. ATLAPI AtlIPersistStreamInit_Save(LPSTREAM pStm,
  74.     BOOL /* fClearDirty */, ATL_PROPMAP_ENTRY* pMap,
  75.     void* pThis, IUnknown* pUnk)
  76. {
  77.     ATLASSERT(pMap != NULL);
  78.     DWORD dw = _ATL_VER;
  79.     HRESULT hr = pStm->Write(&dw, sizeof(DWORD), NULL);
  80.     if (FAILED(hr))
  81.         return hr;
  82.  
  83.     CComPtr<IDispatch> pDispatch;
  84.     const IID* piidOld = NULL;
  85.     for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  86.     {
  87.         if (pMap[i].szDesc == NULL)
  88.             continue;
  89.  
  90.         // check if raw data entry
  91.         if (pMap[i].dwSizeData != 0)
  92.         {
  93.             void* pData = (void*) (pMap[i].dwOffsetData + (DWORD)pThis);
  94.             hr = pStm->Write(pData, pMap[i].dwSizeData, NULL);
  95.             if (FAILED(hr))
  96.                 return hr;
  97.             continue;
  98.         }
  99.  
  100.         CComVariant var;
  101.         if (pMap[i].piidDispatch != piidOld)
  102.         {
  103.             pDispatch.Release();
  104.             if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  105.             {
  106.                 ATLTRACE2(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  107.                 hr = E_FAIL;
  108.                 break;
  109.             }
  110.             piidOld = pMap[i].piidDispatch;
  111.         }
  112.  
  113.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  114.         {
  115.             ATLTRACE2(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  116.             hr = E_FAIL;
  117.             break;
  118.         }
  119.  
  120.         hr = var.WriteToStream(pStm);
  121.         if (FAILED(hr))
  122.             break;
  123.     }
  124.     return hr;
  125. }
  126.  
  127. ATLAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk)
  128. {
  129.     USES_CONVERSION;
  130.     CComPtr<IDispatch> pDispatch;
  131.     const IID* piidOld = NULL;
  132.     for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  133.     {
  134.         if (pMap[i].szDesc == NULL)
  135.             continue;
  136.  
  137.         CComVariant var;
  138.  
  139.         // If raw entry skip it - we don't handle it for property bags just yet
  140.         if (pMap[i].dwSizeData != 0)
  141.         {
  142.             void* pData = (void*) (pMap[i].dwOffsetData + (DWORD)pThis);
  143.             HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog);
  144.             if (SUCCEEDED(hr))
  145.             {
  146.                 // check the type - we only deal with limited set
  147.                 switch (pMap[i].vt)
  148.                 {
  149.                 case VT_UI1:
  150.                 case VT_I1:
  151.                     *((BYTE*)pData) = var.bVal;
  152.                     break;
  153.                 case VT_BOOL:
  154.                     *((VARIANT_BOOL*)pData) = var.boolVal;
  155.                     break;
  156.                 case VT_UI2:
  157.                     *((short*)pData) = var.iVal;
  158.                     break;
  159.                 case VT_UI4:
  160.                 case VT_INT:
  161.                 case VT_UINT:
  162.                     *((long*)pData) = var.lVal;
  163.                     break;
  164.                 }
  165.             }
  166.             continue;
  167.         }
  168.  
  169.         if (pMap[i].piidDispatch != piidOld)
  170.         {
  171.             pDispatch.Release();
  172.             if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  173.             {
  174.                 ATLTRACE2(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  175.                 return E_FAIL;
  176.             }
  177.             piidOld = pMap[i].piidDispatch;
  178.         }
  179.  
  180.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  181.         {
  182.             ATLTRACE2(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  183.             return E_FAIL;
  184.         }
  185.  
  186.         HRESULT hr = pPropBag->Read(pMap[i].szDesc, &var, pErrorLog);
  187.         if (FAILED(hr))
  188.         {
  189.             if (hr == E_INVALIDARG)
  190.             {
  191.                 ATLTRACE2(atlTraceCOM, 0, _T("Property %s not in Bag\n"), OLE2CT(pMap[i].szDesc));
  192.             }
  193.             else
  194.             {
  195.                 // Many containers return different ERROR values for Member not found
  196.                 ATLTRACE2(atlTraceCOM, 0, _T("Error attempting to read Property %s from PropertyBag \n"), OLE2CT(pMap[i].szDesc));
  197.             }
  198.             continue;
  199.         }
  200.  
  201.         if (FAILED(CComDispatchDriver::PutProperty(pDispatch, pMap[i].dispid, &var)))
  202.         {
  203.             ATLTRACE2(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  204.             return E_FAIL;
  205.         }
  206.     }
  207.     return S_OK;
  208. }
  209.  
  210. ATLAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag,
  211.     BOOL /* fClearDirty */, BOOL /* fSaveAllProperties */,
  212.     ATL_PROPMAP_ENTRY* pMap, void* pThis, IUnknown* pUnk)
  213. {
  214.     if (pPropBag == NULL)
  215.     {
  216.         ATLTRACE2(atlTraceCOM, 0, _T("PropBag pointer passed in was invalid\n"));
  217.         return E_POINTER;
  218.     }
  219.  
  220.     CComPtr<IDispatch> pDispatch;
  221.     const IID* piidOld = NULL;
  222.     for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  223.     {
  224.         if (pMap[i].szDesc == NULL)
  225.             continue;
  226.  
  227.         CComVariant var;
  228.  
  229.         // If raw entry skip it - we don't handle it for property bags just yet
  230.         if (pMap[i].dwSizeData != 0)
  231.         {
  232.             void* pData = (void*) (pMap[i].dwOffsetData + (DWORD)pThis);
  233.             // check the type - we only deal with limited set
  234.             bool bTypeOK = false;
  235.             switch (pMap[i].vt)
  236.             {
  237.             case VT_UI1:
  238.             case VT_I1:
  239.                 var.bVal = *((BYTE*)pData);
  240.                 bTypeOK = true;
  241.                 break;
  242.             case VT_BOOL:
  243.                 var.boolVal = *((VARIANT_BOOL*)pData);
  244.                 bTypeOK = true;
  245.                 break;
  246.             case VT_UI2:
  247.                 var.iVal = *((short*)pData);
  248.                 bTypeOK = true;
  249.                 break;
  250.             case VT_UI4:
  251.             case VT_INT:
  252.             case VT_UINT:
  253.                 var.lVal = *((long*)pData);
  254.                 bTypeOK = true;
  255.                 break;
  256.             }
  257.             if (bTypeOK)
  258.             {
  259.                 var.vt = pMap[i].vt;
  260.                 HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var);
  261.                 if (FAILED(hr))
  262.                     return hr;
  263.             }
  264.             continue;
  265.         }
  266.  
  267.         if (pMap[i].piidDispatch != piidOld)
  268.         {
  269.             pDispatch.Release();
  270.             if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch)))
  271.             {
  272.                 ATLTRACE2(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
  273.                 return E_FAIL;
  274.             }
  275.             piidOld = pMap[i].piidDispatch;
  276.         }
  277.  
  278.         if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var)))
  279.         {
  280.             ATLTRACE2(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
  281.             return E_FAIL;
  282.         }
  283.  
  284.         if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH)
  285.         {
  286.             if (var.punkVal == NULL)
  287.             {
  288.                 ATLTRACE2(atlTraceCOM, 0, _T("Warning skipping empty IUnknown in Save\n"));
  289.                 continue;
  290.             }
  291.         }
  292.  
  293.         HRESULT hr = pPropBag->Write(pMap[i].szDesc, &var);
  294.         if (FAILED(hr))
  295.             return hr;
  296.     }
  297.     return S_OK;
  298. }
  299.  
  300. ATLAPI AtlGetObjectSourceInterface(IUnknown* punkObj, GUID* plibid, IID* piid, unsigned short* pdwMajor, unsigned short* pdwMinor)
  301. {
  302.     HRESULT hr = E_FAIL;
  303.     if (punkObj != NULL)
  304.     {
  305.         CComPtr<IDispatch> spDispatch;
  306.         hr = punkObj->QueryInterface(IID_IDispatch, (void**)&spDispatch);
  307.         if (SUCCEEDED(hr))
  308.         {
  309.             CComPtr<ITypeInfo> spTypeInfo;
  310.             hr = spDispatch->GetTypeInfo(0, 0, &spTypeInfo);
  311.             if (SUCCEEDED(hr))
  312.             {
  313.                 CComPtr<ITypeLib> spTypeLib;
  314.                 hr = spTypeInfo->GetContainingTypeLib(&spTypeLib, 0);
  315.                 if (SUCCEEDED(hr))
  316.                 {
  317.                     TLIBATTR* plibAttr;
  318.                     hr = spTypeLib->GetLibAttr(&plibAttr);
  319.                     if (SUCCEEDED(hr))
  320.                     {
  321.                         memcpy(plibid, &plibAttr->guid, sizeof(GUID));
  322.                         *pdwMajor = plibAttr->wMajorVerNum;
  323.                         *pdwMinor = plibAttr->wMinorVerNum;
  324.                         spTypeLib->ReleaseTLibAttr(plibAttr);
  325.                         // First see if the object is willing to tell us about the
  326.                         // default source interface via IProvideClassInfo2
  327.                         CComPtr<IProvideClassInfo2> spInfo;
  328.                         hr = punkObj->QueryInterface(IID_IProvideClassInfo2, (void**)&spInfo);
  329.                         if (SUCCEEDED(hr) && spInfo != NULL)
  330.                             hr = spInfo->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid);
  331.                         else
  332.                         {
  333.                             // No, we have to go hunt for it
  334.                             CComPtr<ITypeInfo> spInfoCoClass;
  335.                             // If we have a clsid, use that
  336.                             // Otherwise, try to locate the clsid from IPersist
  337.                             CComPtr<IPersist> spPersist;
  338.                             CLSID clsid;
  339.                             hr = punkObj->QueryInterface(IID_IPersist, (void**)&spPersist);
  340.                             if (SUCCEEDED(hr))
  341.                             {
  342.                                 hr = spPersist->GetClassID(&clsid);
  343.                                 if (SUCCEEDED(hr))
  344.                                 {
  345.                                     hr = spTypeLib->GetTypeInfoOfGuid(clsid, &spInfoCoClass);
  346.                                     if (SUCCEEDED(hr))
  347.                                     {
  348.                                         TYPEATTR* pAttr=NULL;
  349.                                         spInfoCoClass->GetTypeAttr(&pAttr);
  350.                                         if (pAttr != NULL)
  351.                                         {
  352.                                             HREFTYPE hRef;
  353.                                             for (int i = 0; i < pAttr->cImplTypes; i++)
  354.                                             {
  355.                                                 int nType;
  356.                                                 hr = spInfoCoClass->GetImplTypeFlags(i, &nType);
  357.                                                 if (SUCCEEDED(hr))
  358.                                                 {
  359.                                                     if (nType == (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE))
  360.                                                     {
  361.                                                         // we found it
  362.                                                         hr = spInfoCoClass->GetRefTypeOfImplType(i, &hRef);
  363.                                                         if (SUCCEEDED(hr))
  364.                                                         {
  365.                                                             CComPtr<ITypeInfo> spInfo;
  366.                                                             hr = spInfoCoClass->GetRefTypeInfo(hRef, &spInfo);
  367.                                                             if (SUCCEEDED(hr))
  368.                                                             {
  369.                                                                 TYPEATTR* pAttrIF;
  370.                                                                 spInfo->GetTypeAttr(&pAttrIF);
  371.                                                                 if (pAttrIF != NULL)
  372.                                                                 {
  373.                                                                     memcpy(piid, &pAttrIF->guid, sizeof(GUID));
  374.                                                                 }
  375.                                                                 spInfo->ReleaseTypeAttr(pAttrIF);
  376.                                                             }
  377.                                                         }
  378.                                                         break;
  379.                                                     }
  380.                                                 }
  381.                                             }
  382.                                             spInfoCoClass->ReleaseTypeAttr(pAttr);
  383.                                         }
  384.                                     }
  385.                                 }
  386.                             }
  387.                         }
  388.                     }
  389.                 }
  390.             }
  391.         }
  392.     }
  393.     return hr;
  394. }
  395. #endif // !_ATL_DLL
  396.  
  397. extern "C" {
  398.  
  399. /////////////////////////////////////////////////////////////////////////////
  400. // MIPS R4000 version
  401.  
  402. #ifdef _MIPS_
  403.  
  404. extern "C" void _asm(char *, ...);
  405.  
  406. void __stdcall
  407. _AtlCEDispatchCall(DWORD /*pfn*/, void* /*pArgs*/, UINT /*nSizeArgs*/)
  408. {
  409.     _asm("addiu     %sp,%a1,0x0");      // sp = pArgs
  410.     _asm("addiu     %t6,%a0,0x0");      // t6 = pfn (save it)
  411.     _asm("lw        %a0,0x0(%sp)");     // a0 = param0
  412.     _asm("lw        %a1,0x4(%sp)");     // a1 = param1
  413.     _asm("lw        %a2,0x8(%sp)");     // a2 = param2
  414.     _asm("lw        %a3,0xc(%sp)");     // a3 = param3
  415.     _asm("j         %t6");              // ip = pfn (jump to target function)
  416. }
  417.  
  418. #endif // _MIPS_
  419.  
  420.  
  421. #if defined(x86) || defined(_WIN32_WCE_EMULATION)
  422.  
  423. __declspec(naked) void __stdcall
  424. _AtlCEDispatchCall(DWORD /*pfn*/, void* /*pArgs*/, UINT /*nSizeArgs*/)
  425. {
  426.     _asm
  427.     {
  428.         pop     edx         // edx = return address
  429.         pop     eax         // eax = pfn
  430.         pop     ecx         // ecx = pArgs
  431.         add     ecx,[esp]   // ecx += nSizeArgs (=scratch area)
  432.         mov     [ecx],edx   // scratch[0] = return address
  433.         sub     ecx,[esp]   // ecx = pArgs (again)
  434.         mov     esp,ecx     // esp = pArgs (usually already correct)
  435. #if !defined(_WIN32_WCE_EMULATION)
  436. // For emulation, we are using the __stdcall calling convention, which implies 
  437. // that 'this' is the last argument pushed on the stack, so don't pop it.
  438.         pop     ecx         // ecx = this pointer (the CCmdTarget*)
  439. #endif // _WIN32_WCE_EMULATION
  440.         call    eax         // call member function
  441.         ret                 // esp[0] should = scratch[0] = return address
  442.     }
  443. }
  444.  
  445. #endif // x86 || x86em
  446.  
  447. /////////////////////////////////////////////////////////////////////////////
  448. // SH version
  449.  
  450. #if defined(SHx)
  451.  
  452. void __stdcall _AtlCEDispatchCall(DWORD /*pfn*/, void* /*pArgs*/, UINT /*nSizeArgs*/)
  453. {
  454.     __asm("mov   R5, sp");                // sp = pStack
  455.     __asm("mov   R4, R1");                // R1 = pfn (save it)
  456.     __asm("mov.l @sp, R4");               // R4 = arg1 ('this' pointer)
  457.     __asm("mov   #4, R0");                // R5 = arg2
  458.     __asm("mov.l @(R0,sp), R5");
  459.     __asm("mov   #8, R0");                // R6 = arg3
  460.     __asm("mov.l @(R0,sp), R6");
  461.     __asm("mov  #12, R0");                // R7 = arg4
  462.     // __asm("mov.l @(R0,sp), R7"); moved to delay slot
  463.     __asm("jmp  @R1\n"                    // jump to target function
  464.           "mov.l @(R0,sp), R7");
  465. }
  466.  
  467. #endif // SHx
  468.  
  469. #ifdef _ARM_
  470. void __stdcall _AtlCEDispatchCall(DWORD /*pfn*/, void* /*pArgs*/, UINT /*nSizeArgs*/)
  471. {
  472.     // Set up the stack pointer. Note that the first four dwords of arguments
  473.     // are saved on the callee's stack so 16 is added to the pointer to
  474.     // the arguments.
  475.     __emit(0xe281d010);     // add  sp, r1, #16
  476.  
  477.     // Save the function pointer in r12 (the only available scratch register)
  478.     __emit(0xe1a0c000);     // mov  r12, r0
  479.  
  480.     // Copy four words of arguments into r0-r3
  481.     __emit(0xe5910000);     // ldr  r0, [r1]
  482.     __emit(0xe5912008);     // ldr  r2, [r1, #8]
  483.     __emit(0xe591300c);     // ldr  r3, [r1, #12]
  484.     __emit(0xe5911004);     // ldr  r1, [r1, #4]
  485.  
  486.     // Jump to the function
  487.     __emit(0xe1a0f00c);     // mov  pc, r12
  488. }
  489. #endif // _ARM_
  490.  
  491.  
  492. #ifdef _PPC_
  493. void __stdcall _AtlCEDispatchCall(DWORD /*pfn*/, void* /*pArgs*/, UINT /*nSizeArgs*/)
  494. {
  495.     __emit(0x7C812378); // mr          r1,r4
  496.     __emit(0x7C6903A6); // mtctr       r3
  497.     __emit(0x80610000); // lwz         r3,0(r1)
  498.     __emit(0x80810004); // lwz         r4,4(r1)
  499.     __emit(0x80A10008); // lwz         r5,8(r1)
  500.     __emit(0x80C1000C); // lwz         r6,0Ch(r1)
  501.     __emit(0x4E800420); // bctr
  502. }
  503. #endif // PPC
  504.  
  505. /////////////////////////////////////////////////////////////////////////////
  506. // DEC Alpha AXP version
  507.  
  508. #ifdef _ALPHA_
  509.  
  510. // Note: ALPHA version is in src\alpha\olecall_.s
  511.  
  512. // The ALPHA compiler does not support inline assembly, so it
  513. //  must be build separately with the ASAXP assembler.
  514.  
  515. #endif // _ALPHA_
  516.  
  517. } // end extern "C" block
  518.  
  519. } //namespace ATL
  520.  
  521. #endif // !_ATL_DLL
  522.  
  523. ////////////////////////////////////////////////////////////////////////////
  524. //
  525. //  CStreamImp::CStreamImp
  526. //
  527. ////////////////////////////////////////////////////////////////////////////
  528.  
  529. ////////////////////////////////////////////////////////////////////////////
  530. //
  531. #define TRACE_STG 0
  532. #define MAX_POSSIBLE_NAMELEN    512
  533. #define MAGIC_STORAGE    0x1234
  534. #define MAGIC_STREAM    0xabcd
  535.  
  536.  
  537. class CStreamImp;
  538.  
  539. class CStorageImp : public IStorage
  540. {
  541. public:
  542.     CStorageImp(
  543.          const OLECHAR      *pwcsName,
  544.          CStorageImp        *pParent,
  545.          CStorageImp        *pSibling,
  546.          CRITICAL_SECTION   *pCS,
  547.          HRESULT *phr);
  548.  
  549.     ~CStorageImp();
  550.  
  551.     STDMETHOD(QueryInterface) (REFIID iid, LPVOID *ppvObj);
  552.     STDMETHOD_(ULONG, AddRef) ();
  553.     STDMETHOD_(ULONG, Release) ();
  554.  
  555.     HRESULT STDMETHODCALLTYPE CreateStream(
  556.          const OLECHAR *pwcsName,
  557.          DWORD grfMode,
  558.          DWORD reserved1,
  559.          DWORD reserved2,
  560.          IStream **ppstm);
  561.     HRESULT STDMETHODCALLTYPE OpenStream(
  562.          const OLECHAR *pwcsName,
  563.          void *reserved1,
  564.          DWORD grfMode,
  565.          DWORD reserved2,
  566.          IStream **ppstm);
  567.     HRESULT STDMETHODCALLTYPE CreateStorage(
  568.          const OLECHAR *pwcsName,
  569.          DWORD grfMode,
  570.          DWORD dwStgFmt,
  571.          DWORD reserved2,
  572.          IStorage **ppstg);
  573.     HRESULT STDMETHODCALLTYPE OpenStorage(
  574.          const OLECHAR *pwcsName,
  575.          IStorage *pstgPriority,
  576.          DWORD grfMode,
  577.          SNB snbExclude,
  578.          DWORD reserved,
  579.          IStorage **ppstg);
  580.     HRESULT STDMETHODCALLTYPE CopyTo(
  581.          DWORD ciidExclude,
  582.          const IID *rgiidExclude,
  583.          SNB snbExclude,
  584.          IStorage *pstgDest);
  585.     HRESULT STDMETHODCALLTYPE MoveElementTo(
  586.          const OLECHAR *pwcsName,
  587.          IStorage *pstgDest,
  588.          const OLECHAR *pwcsNewName,
  589.          DWORD grfFlags);
  590.     HRESULT STDMETHODCALLTYPE Commit(
  591.          DWORD grfCommitFlags);
  592.     HRESULT STDMETHODCALLTYPE Revert( void);
  593.     HRESULT STDMETHODCALLTYPE EnumElements(
  594.          DWORD reserved1,
  595.          void *reserved2,
  596.          DWORD reserved3,
  597.          IEnumSTATSTG **ppenum);
  598.     HRESULT STDMETHODCALLTYPE DestroyElement(
  599.          const OLECHAR *pwcsName);
  600.     HRESULT STDMETHODCALLTYPE RenameElement(
  601.          const OLECHAR *pwcsOldName,
  602.          const OLECHAR *pwcsNewName);
  603.     HRESULT STDMETHODCALLTYPE SetElementTimes(
  604.          const OLECHAR *pwcsName,
  605.          const FILETIME *pctime,
  606.          const FILETIME *patime,
  607.          const FILETIME *pmtime);
  608.     HRESULT STDMETHODCALLTYPE SetClass(
  609.          REFCLSID clsid);
  610.     HRESULT STDMETHODCALLTYPE SetStateBits(
  611.          DWORD grfStateBits,
  612.          DWORD grfMask);
  613.     HRESULT STDMETHODCALLTYPE Stat(
  614.          STATSTG *pstatstg,
  615.          DWORD grfStatFlag);
  616.     HRESULT STDMETHODCALLTYPE Load(
  617.          HANDLE hFile);
  618.     HRESULT STDMETHODCALLTYPE Save(
  619.          HANDLE hFile);
  620.  
  621.     friend class CStreamImp;
  622.     friend class CEnumSTATSTGImp;
  623.  
  624. private:
  625.     OLECHAR*        m_pszName;
  626.     CLSID           m_clsid;
  627.     CStreamImp*     m_pFirstChildStream;
  628.     CStorageImp*    m_pFirstChildStorage;
  629.     CStorageImp*    m_pNextStorage;
  630.     CStorageImp*    m_pParentStorage;
  631.     CRITICAL_SECTION* m_pCS;
  632.     ULONG           m_Refs;
  633. };
  634.  
  635. class CStreamImp : public IStream
  636. {
  637. public:
  638.     CStreamImp(
  639.         const OLECHAR       *pszName,
  640.         CStreamImp          *pSibling,
  641.         CStorageImp         *pParent,
  642.         CRITICAL_SECTION    *pCS,
  643.         HRESULT             *phr,
  644.         PBYTE               pData = NULL,
  645.         BOOL                fDeleteOnRelease = TRUE);
  646.  
  647.     ~CStreamImp();
  648.  
  649.     STDMETHOD(QueryInterface) (REFIID iid, LPVOID *ppvObj);
  650.     STDMETHOD_(ULONG, AddRef) ();
  651.     STDMETHOD_(ULONG, Release) ();
  652.     HRESULT STDMETHODCALLTYPE Read(
  653.         void *pv,
  654.         ULONG cb,
  655.         ULONG *pcbRead);
  656.     HRESULT STDMETHODCALLTYPE Write(
  657.         const void *pv,
  658.         ULONG cb,
  659.         ULONG *pcbWritten);
  660.     HRESULT STDMETHODCALLTYPE Seek(
  661.          LARGE_INTEGER dlibMove,
  662.          DWORD dwOrigin,
  663.          ULARGE_INTEGER *plibNewPosition);
  664.     HRESULT STDMETHODCALLTYPE SetSize(
  665.          ULARGE_INTEGER libNewSize);
  666.     HRESULT STDMETHODCALLTYPE CopyTo(
  667.          IStream *pstm,
  668.          ULARGE_INTEGER cb,
  669.          ULARGE_INTEGER *pcbRead,
  670.          ULARGE_INTEGER *pcbWritten);
  671.     HRESULT STDMETHODCALLTYPE Commit(
  672.          DWORD grfCommitFlags);
  673.     HRESULT STDMETHODCALLTYPE Revert( void);
  674.     HRESULT STDMETHODCALLTYPE LockRegion(
  675.          ULARGE_INTEGER libOffset,
  676.          ULARGE_INTEGER cb,
  677.          DWORD dwLockType);
  678.     HRESULT STDMETHODCALLTYPE UnlockRegion(
  679.          ULARGE_INTEGER libOffset,
  680.          ULARGE_INTEGER cb,
  681.          DWORD dwLockType);
  682.     HRESULT STDMETHODCALLTYPE Stat(
  683.          STATSTG *pstatstg,
  684.          DWORD grfStatFlag);
  685.     HRESULT STDMETHODCALLTYPE Clone(
  686.          IStream **ppstm);
  687.     HRESULT STDMETHODCALLTYPE Load(
  688.          HANDLE hFile);
  689.     HRESULT STDMETHODCALLTYPE Save(
  690.          HANDLE hFile);
  691.  
  692.     friend class CStorageImp;
  693.     friend class CEnumSTATSTGImp;
  694.  
  695. private:
  696.     PBYTE       m_pData;
  697.     CStreamImp* m_pNext;
  698.     OLECHAR*    m_pszName;
  699.     DWORD       m_dwSize;
  700.     DWORD       m_dwCurrentPosition;
  701.     ULONG       m_Refs;
  702.     BOOL        m_fDeleteOnRelease;
  703.     CStorageImp*        m_pParent;
  704.     CRITICAL_SECTION*   m_pCS;
  705. };
  706.  
  707.  
  708. CStreamImp::CStreamImp(
  709.     const OLECHAR       *pszName,
  710.     CStreamImp          *pSibling,
  711.     CStorageImp         *pParent,
  712.     CRITICAL_SECTION    *pCS,
  713.     HRESULT             *phr,
  714.     PBYTE               pData,
  715.     BOOL                fDeleteOnRelease)
  716. {
  717.     m_dwSize = 0;
  718.     if (pData != NULL)
  719.     {
  720.         m_dwSize = ::LocalSize(pData);
  721.     }
  722.     m_fDeleteOnRelease = fDeleteOnRelease;
  723.     m_dwCurrentPosition = 0;
  724.     m_pData = pData;
  725.     m_Refs = 1;
  726.     m_pParent = pParent;
  727.     m_pNext = pSibling;
  728. //    m_pCS = pCS;
  729.  
  730.     if (pszName != NULL)
  731.     {
  732.         m_pszName = new OLECHAR[lstrlen(pszName) + 1];
  733.         if (m_pszName == NULL)
  734.         {
  735.             *phr = STG_E_INSUFFICIENTMEMORY;
  736.             return;
  737.         }
  738.         lstrcpy(m_pszName, pszName);
  739.     }
  740.     else
  741.     {
  742.         m_pszName = NULL;
  743.     }
  744.  
  745.     *phr = S_OK;
  746. }
  747.  
  748. ////////////////////////////////////////////////////////////////////////////
  749. //
  750. CStreamImp::~CStreamImp()
  751. {
  752.     if (m_fDeleteOnRelease)
  753.     {
  754.         CoTaskMemFree(m_pData);
  755.     }
  756.     delete[] m_pszName;
  757.     if (m_pParent == NULL)
  758.     {
  759. //        DeleteCriticalSection(m_pCS);
  760.         delete m_pCS;
  761.     }
  762. }
  763.  
  764. ////////////////////////////////////////////////////////////////////////////
  765. //
  766. ULONG CStreamImp::AddRef()
  767. {
  768.     if (m_pParent != NULL)
  769.     {
  770.         return m_pParent->AddRef();
  771.     }
  772.  
  773.     InterlockedIncrement((LONG*)&m_Refs);
  774.     return m_Refs;
  775. }
  776.  
  777. ////////////////////////////////////////////////////////////////////////////
  778. //
  779. ULONG CStreamImp::Release()
  780. {
  781.     ULONG Refs;
  782.  
  783.     if (m_pParent != NULL)
  784.     {
  785.         return m_pParent->Release();
  786.     }
  787.  
  788.     Refs = m_Refs;
  789.     if (InterlockedDecrement((LONG*)&m_Refs) == 0)
  790.     {
  791.         delete this;
  792.         return 0;
  793.     }
  794.  
  795.     return Refs;
  796. }
  797.  
  798. ////////////////////////////////////////////////////////////////////////////
  799. //
  800. HRESULT CStreamImp::QueryInterface(REFIID riid, LPVOID *ppv)
  801. {
  802.     if (IsEqualIID(riid, IID_IUnknown) ||
  803.         IsEqualIID(riid, IID_IStream))
  804.     {
  805.         *ppv = (LPUNKNOWN) this ;
  806.         AddRef();
  807.         return S_OK;
  808.     }
  809.  
  810.     *ppv = NULL;
  811.     return E_NOINTERFACE ;
  812. }
  813.  
  814. ////////////////////////////////////////////////////////////////////////////
  815. //
  816. HRESULT CStreamImp::Read(
  817.         void *pv,
  818.         ULONG cb,
  819.         ULONG *pcbRead)
  820. {
  821.     ULONG cbRead = 0;
  822.  
  823.     DEBUGMSG(TRACE_STG, (L"CStreamImp::Read(%X,%d)\n",pv,cb));
  824.  
  825.     //
  826.     //  Make sure the current position is within the data
  827.     //
  828.  
  829. //    EnterCriticalSection(m_pCS);
  830.  
  831.     if (m_dwSize > m_dwCurrentPosition)
  832.     {
  833.         if (cb > (m_dwSize - m_dwCurrentPosition))
  834.         {
  835.             cbRead = m_dwSize - m_dwCurrentPosition;
  836.         }
  837.         else
  838.         {
  839.             cbRead = cb;
  840.         }
  841.  
  842.         memcpy(
  843.             pv,
  844.             m_pData + m_dwCurrentPosition,
  845.             cbRead);
  846.  
  847.         m_dwCurrentPosition += cbRead;
  848.     }
  849.  
  850. //    LeaveCriticalSection(m_pCS);
  851.  
  852.     if (pcbRead != NULL)
  853.     {
  854.         *pcbRead = cbRead;
  855.     }
  856.  
  857.     return S_OK;
  858. }
  859.  
  860. ////////////////////////////////////////////////////////////////////////////
  861. //
  862. HRESULT CStreamImp::Write(
  863.         const void *pv,
  864.         ULONG cb,
  865.         ULONG *pcbWritten)
  866. {
  867.     DEBUGMSG(TRACE_STG, (L"CStreamImp::Write\n"));
  868.  
  869. //    EnterCriticalSection(m_pCS);
  870.  
  871.     if ((m_dwCurrentPosition + cb) > (unsigned)m_dwSize)
  872.     {
  873.         //
  874.         //  We try and grow ourselves here
  875.         //
  876.  
  877.         PBYTE pData = (PBYTE)CoTaskMemRealloc(
  878.                     m_pData,
  879.                     (m_dwCurrentPosition + cb));
  880.  
  881.         if (pData == NULL)
  882.         {
  883. //            LeaveCriticalSection(m_pCS);
  884.             return STG_E_MEDIUMFULL;
  885.         }
  886.  
  887.         m_dwSize = m_dwCurrentPosition + cb;
  888.         m_pData = pData;
  889.     }
  890.  
  891.     //
  892.     //  Copy the data
  893.     //
  894.  
  895.     memcpy(m_pData + m_dwCurrentPosition, pv, cb);
  896.  
  897.     if (pcbWritten != NULL)
  898.     {
  899.         *pcbWritten = cb;
  900.     }
  901.  
  902.     //
  903.     //  Update our position
  904.     //
  905.  
  906.     m_dwCurrentPosition += cb;
  907.  
  908. //    LeaveCriticalSection(m_pCS);
  909.  
  910.     return S_OK;
  911. }
  912.  
  913. ////////////////////////////////////////////////////////////////////////////
  914. //
  915. HRESULT CStreamImp::Seek(
  916.      LARGE_INTEGER dlibMove,
  917.      DWORD dwOrigin,
  918.      ULARGE_INTEGER *plibNewPosition)
  919. {
  920.     LONG lMove = (LONG)dlibMove.QuadPart;
  921.  
  922.     DEBUGMSG(
  923.         TRACE_STG,
  924.         (L"CStreamImp::Seek(%ld,%X,%ld)\n",lMove,
  925.         dwOrigin,m_dwCurrentPosition));
  926.  
  927. //    EnterCriticalSection(m_pCS);
  928.  
  929.     switch (dwOrigin)
  930.     {
  931.     case STREAM_SEEK_CUR:
  932.  
  933.  
  934.         lMove += (LONG)m_dwCurrentPosition;
  935.  
  936.         // Fall through
  937.  
  938.     case STREAM_SEEK_SET:
  939.  
  940.         // Make sure we don't go past the begining
  941.  
  942.         if (lMove < 0)
  943.         {
  944. //            LeaveCriticalSection(m_pCS);
  945.             return STG_E_INVALIDPOINTER;
  946.         }
  947.  
  948.         m_dwCurrentPosition = (DWORD)lMove;
  949.         break;
  950.  
  951.     case STREAM_SEEK_END:
  952.  
  953.         // Make sure we don't go past the begining
  954.         if (lMove > (LONG)m_dwSize)
  955.         {
  956. //            LeaveCriticalSection(m_pCS);
  957.             return STG_E_INVALIDPOINTER;
  958.         }
  959.  
  960.         m_dwCurrentPosition = (DWORD)((LONG)m_dwSize - lMove);
  961.         break;
  962.  
  963.     default:
  964. //        LeaveCriticalSection(m_pCS);
  965.         return STG_E_INVALIDFUNCTION;
  966.  
  967.     }
  968.  
  969.     //
  970.     //  Return the new position if the user asked for it.
  971.     //
  972.  
  973.     if (plibNewPosition != NULL)
  974.     {
  975.         plibNewPosition->QuadPart = m_dwCurrentPosition;
  976.     }
  977.  
  978. //    LeaveCriticalSection(m_pCS);
  979.     return S_OK;
  980. }
  981.  
  982. ////////////////////////////////////////////////////////////////////////////
  983. //
  984. HRESULT CStreamImp::SetSize(
  985.      ULARGE_INTEGER libNewSize)
  986. {
  987.     PBYTE pData;
  988.  
  989.     DEBUGMSG(TRACE_STG, (L"CStreamImp::SetSize\n"));
  990.  
  991. //    EnterCriticalSection(m_pCS);
  992.  
  993.     pData = (PBYTE)CoTaskMemRealloc(
  994.                 m_pData,
  995.                 libNewSize.LowPart);
  996.  
  997.     if (pData == NULL)
  998.     {
  999. //        LeaveCriticalSection(m_pCS);
  1000.         return STG_E_MEDIUMFULL;
  1001.     }
  1002.  
  1003.     m_dwSize = libNewSize.LowPart;
  1004.     m_pData = pData;
  1005.  
  1006. //    LeaveCriticalSection(m_pCS);
  1007.  
  1008.     return S_OK;
  1009. }
  1010.  
  1011. ////////////////////////////////////////////////////////////////////////////
  1012. //
  1013. HRESULT CStreamImp::CopyTo(
  1014.      IStream *pstm,
  1015.      ULARGE_INTEGER cb,
  1016.      ULARGE_INTEGER *pcbRead,
  1017.      ULARGE_INTEGER *pcbWritten)
  1018. {
  1019.     return E_NOTIMPL;
  1020. }
  1021.  
  1022. ////////////////////////////////////////////////////////////////////////////
  1023. //
  1024. HRESULT CStreamImp::Commit(
  1025.      DWORD grfCommitFlags)
  1026. {
  1027.     return E_NOTIMPL;
  1028. }
  1029.  
  1030. ////////////////////////////////////////////////////////////////////////////
  1031. //
  1032. HRESULT CStreamImp::Revert( void)
  1033. {
  1034.     return E_NOTIMPL;
  1035. }
  1036.  
  1037. ////////////////////////////////////////////////////////////////////////////
  1038. //
  1039. HRESULT CStreamImp::LockRegion(
  1040.      ULARGE_INTEGER libOffset,
  1041.      ULARGE_INTEGER cb,
  1042.      DWORD dwLockType)
  1043. {
  1044.     return E_NOTIMPL;
  1045. }
  1046.  
  1047. ////////////////////////////////////////////////////////////////////////////
  1048. //
  1049. HRESULT CStreamImp::UnlockRegion(
  1050.      ULARGE_INTEGER libOffset,
  1051.      ULARGE_INTEGER cb,
  1052.      DWORD dwLockType)
  1053. {
  1054.     return E_NOTIMPL;
  1055. }
  1056.  
  1057. ////////////////////////////////////////////////////////////////////////////
  1058. //
  1059. HRESULT CStreamImp::Stat(
  1060.      STATSTG *pstatstg,
  1061.      DWORD grfStatFlag)
  1062. {
  1063.     return E_NOTIMPL;
  1064. }
  1065.  
  1066. ////////////////////////////////////////////////////////////////////////////
  1067. //
  1068. HRESULT CStreamImp::Clone(
  1069.      IStream **ppstm)
  1070. {
  1071.     if (ppstm != NULL)
  1072.     {
  1073.         *ppstm = (IStream*)m_pData;
  1074.     }
  1075.     return E_NOTIMPL;
  1076. }
  1077.  
  1078. ////////////////////////////////////////////////////////////////////////////
  1079. //
  1080. HRESULT CStreamImp::Load(HANDLE hFile)
  1081. {
  1082.     DWORD    dwMagic,dwSize,dwRW;
  1083.  
  1084.     DEBUGMSG(TRACE_STG, (L"CStreamImp::Load(%s)\n", m_pszName));
  1085.  
  1086.     //    must be a brand new CStream to call serialize
  1087.     if (m_pszName != NULL || m_pData != NULL)
  1088.     {
  1089.         return STG_E_ACCESSDENIED;
  1090.     }
  1091.  
  1092.     //    make sure the magic number
  1093.     if (!ReadFile(hFile, &dwMagic, sizeof(DWORD), &dwRW, NULL))
  1094.     {
  1095.         return    STG_E_FILEALREADYEXISTS;
  1096.     }
  1097.  
  1098.     if (dwMagic != MAGIC_STREAM)
  1099.     {
  1100.         return    STG_E_FILEALREADYEXISTS;
  1101.     }
  1102.  
  1103.     //    read the name size and name
  1104.     if (!ReadFile(hFile, &dwSize, sizeof(DWORD), &dwRW, NULL))
  1105.     {
  1106.         return STG_E_FILEALREADYEXISTS;
  1107.     }
  1108.  
  1109.     if (dwSize<=0 || dwSize>MAX_POSSIBLE_NAMELEN)
  1110.     {
  1111.         return STG_E_FILEALREADYEXISTS;
  1112.     }
  1113.  
  1114.     m_pszName = new WCHAR[dwSize/sizeof(WCHAR)];
  1115.  
  1116.     if (m_pszName == NULL)
  1117.     {
  1118.         return STG_E_INSUFFICIENTMEMORY;
  1119.     }
  1120.     if (!ReadFile(hFile, m_pszName, dwSize, &dwRW, NULL) || dwRW != dwSize)
  1121.     {
  1122.         return STG_E_FILEALREADYEXISTS;
  1123.     }
  1124.  
  1125.     //    read the data size and data
  1126.     if (!ReadFile(hFile, &m_dwSize, sizeof(DWORD), &dwRW, NULL) || m_dwSize < 0)
  1127.     {
  1128.         return STG_E_FILEALREADYEXISTS;
  1129.     }
  1130.  
  1131.     if (m_dwSize != 0)
  1132.     {
  1133.         m_pData = (PBYTE)CoTaskMemAlloc(m_dwSize);
  1134.  
  1135.         if (m_pData == NULL)
  1136.         {
  1137.             return STG_E_INSUFFICIENTMEMORY;
  1138.         }
  1139.  
  1140.         if (!ReadFile(hFile, m_pData, m_dwSize, &dwRW, NULL) ||
  1141.             (dwRW != m_dwSize))
  1142.         {
  1143.             DEBUGMSG(TRACE_STG,(L"ReadFile Failed %ld %ld %X\n",dwRW, dwSize,GetLastError()));
  1144.             return STG_E_FILEALREADYEXISTS;
  1145.         }
  1146.     }
  1147.  
  1148.     return S_OK;
  1149. }
  1150.  
  1151. ////////////////////////////////////////////////////////////////////////////
  1152. //
  1153. HRESULT CStreamImp::Save(HANDLE hFile)
  1154. {
  1155.     DWORD    dwMagic,dwSize,dwRW;
  1156.  
  1157.     if (m_pszName == NULL)
  1158.     {
  1159.         return STG_E_ACCESSDENIED;
  1160.     }
  1161.  
  1162.     //    first write the storage magic number
  1163.     dwMagic = MAGIC_STREAM;
  1164.     if (!WriteFile(hFile, &dwMagic, sizeof(DWORD), &dwRW, NULL))
  1165.     {
  1166.         return STG_E_MEDIUMFULL;
  1167.     }
  1168.  
  1169.     //    write the size of the name first
  1170.     dwSize = (lstrlen(m_pszName)+1)*sizeof(WCHAR);
  1171.     if(!WriteFile(hFile, &dwSize, sizeof(DWORD), &dwRW, NULL))
  1172.     {
  1173.         return STG_E_MEDIUMFULL;
  1174.     }
  1175.  
  1176.     //    write the name
  1177.     if (!WriteFile(hFile, m_pszName, dwSize, &dwRW, NULL))
  1178.     {
  1179.         return STG_E_MEDIUMFULL;
  1180.     }
  1181.  
  1182.  
  1183.     //    write the data size and data
  1184.     if (!WriteFile(hFile, &m_dwSize, sizeof(DWORD), &dwRW, NULL))
  1185.     {
  1186.         return STG_E_MEDIUMFULL;
  1187.     }
  1188.  
  1189.     if (m_dwSize && !m_pData)
  1190.     {
  1191.         return STG_E_MEDIUMFULL;
  1192.     }
  1193.  
  1194.     if (m_pData)
  1195.     {
  1196.         if(!WriteFile(hFile, m_pData, m_dwSize, &dwRW, NULL))
  1197.         {
  1198.             return STG_E_MEDIUMFULL;
  1199.         }
  1200.     }
  1201.  
  1202.     DEBUGMSG(TRACE_STG, (L"CStreamImp::Save(%s)\n",m_pszName));
  1203.  
  1204.     return    S_OK;
  1205. }
  1206.  
  1207. ///////////////////////////////////////////////////////////////////////////////////////////
  1208.  
  1209. namespace ATL
  1210. {
  1211.  
  1212. HRESULT wce_OleLoadFromStream ( LPSTREAM pStm, REFIID iidInterface, LPVOID FAR* ppvObj)
  1213. {
  1214.     //  Assumptions:  The name of the object class is in the stream,
  1215.     //  as a length-prefixed string.
  1216.     HRESULT         hresult = NOERROR;
  1217.     CLSID               cid;
  1218.     LPPERSISTSTREAM pPS;
  1219.     LPUNKNOWN       pUnk;
  1220.  
  1221.     *ppvObj = NULL;
  1222.  
  1223.     if ((hresult = ::ReadClassStm(pStm, &cid)) != NOERROR)
  1224.         goto errRtn;
  1225.  
  1226.     hresult = ::CoCreateInstance(cid, NULL,
  1227.         CLSCTX_SERVER,
  1228.         iidInterface,
  1229.         (LPVOID FAR *) &pUnk);
  1230.     if (hresult)
  1231.         goto errRtn;
  1232.     hresult = pUnk->QueryInterface(IID_IPersistStream,
  1233.         (LPVOID FAR*) &pPS);
  1234.     if (!hresult)
  1235.     {
  1236.         hresult = pPS->Load( pStm );
  1237.         pPS->Release();
  1238.     }
  1239.     if (!hresult)
  1240.         hresult = pUnk->QueryInterface(iidInterface, ppvObj );
  1241.     pUnk->Release();
  1242.  
  1243. errRtn:
  1244.     return hresult;
  1245. }
  1246.  
  1247. HRESULT wce_OleSaveToStream ( LPPERSISTSTREAM pPStm, LPSTREAM pStm)
  1248. {
  1249.     HRESULT hresult = 0;
  1250.     CLSID   clsid;
  1251.  
  1252.     if (!pPStm)
  1253.     {
  1254.         hresult = ResultFromScode(OLE_E_BLANK);
  1255.         goto errRtn;
  1256.     }
  1257.  
  1258.     if (hresult = pPStm->GetClassID(&clsid))
  1259.         goto errRtn;
  1260.  
  1261.     if ((hresult = ::WriteClassStm(pStm, clsid)) != NOERROR)
  1262.         goto errRtn;
  1263.  
  1264.     hresult = pPStm->Save(pStm, TRUE);
  1265.  
  1266. errRtn:
  1267.     return hresult;
  1268. }
  1269.  
  1270. HRESULT wce_CLSIDFromProgID(LPCOLESTR lpszProgID, LPCLSID pclsid)
  1271. {
  1272. #if (_WIN32_WCE >= 210)
  1273.     return CLSIDFromProgID(lpszProgID,pclsid);
  1274. #else // _WIN32_WCE >= 210
  1275.     // lookup lpsz\\clsid and call CLSIDFromString on the result;
  1276.     WCHAR sz[256];
  1277.     ULONG cbValue = sizeof(sz);
  1278.     HKEY hSubKey;
  1279.     LONG lResult;
  1280.  
  1281.     if (lpszProgID == NULL)
  1282.     {
  1283.         return(E_INVALIDARG);
  1284.     }
  1285.  
  1286.     if (*lpszProgID == 0)
  1287.     {
  1288.         return(CO_E_CLASSSTRING);
  1289.     }
  1290.     _tcscpy(sz, lpszProgID);
  1291.     _tcscat(sz, _T("\\Clsid"));
  1292.  
  1293.     lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, sz, 0, 0, &hSubKey);
  1294.     if (lResult == ERROR_SUCCESS)
  1295.     {
  1296.         TCHAR strValueName[60];
  1297.         DWORD dwValueNameLength;
  1298.         DWORD dwType;
  1299.         lResult = RegEnumValue(hSubKey, 0, strValueName, &dwValueNameLength, 0, &dwType, (LPBYTE)sz, &cbValue);
  1300.         ATLASSERT(dwType == REG_SZ);
  1301.         ATLASSERT(lResult == ERROR_SUCCESS);
  1302.         return CLSIDFromString(sz, pclsid);
  1303.     }
  1304.  
  1305.     return E_FAIL;
  1306. #endif // _WIN32_WCE >= 210
  1307. }
  1308.  
  1309.  
  1310. HRESULT wce_ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lplpszProgID)
  1311. {
  1312.     LPOLESTR lpszCLSID = NULL;
  1313.     WCHAR szKeyCLSID[64];
  1314.     static WCHAR szProgID[64];
  1315.     HKEY hKey;
  1316.     LONG lResult;
  1317.  
  1318.     *lplpszProgID = NULL;
  1319.  
  1320.     if(StringFromCLSID(clsid, &lpszCLSID) == S_OK)
  1321.     {
  1322.         _tcscpy(szKeyCLSID, _T("CLSID\\"));
  1323.         _tcscat(szKeyCLSID, lpszCLSID);
  1324.  
  1325.         lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKeyCLSID, 0, 0, &hKey);
  1326.         if (lResult == ERROR_SUCCESS)
  1327.         {
  1328.             TCHAR strValueName[60];
  1329.             DWORD dwValueNameLength, dwType, cbValue;
  1330.             lResult = RegEnumValue(hKey, 0, strValueName, &dwValueNameLength, 0, &dwType, 
  1331.                                    (LPBYTE)szProgID, &cbValue);
  1332.             if(lResult == ERROR_SUCCESS)
  1333.                 *lplpszProgID = szProgID;
  1334.         }
  1335.  
  1336.         // Free lpszCLSID
  1337.         /*LPMALLOC lpIMalloc = NULL; 
  1338.         if(CoGetMalloc(MEMCTX_TASK, &lpIMalloc) == NOERROR) 
  1339.         { 
  1340.             lpIMalloc->Free((LPVOID)lpszCLSID); 
  1341.             lpIMalloc->Release(); 
  1342.         } */
  1343.         // There's no CoGetMalloc in WCE.  Assuming it uses malloc (same as GlobalAlloc), so use free.
  1344.         free((LPVOID)lpszCLSID);
  1345.     }
  1346.  
  1347.     return (*lplpszProgID != NULL)? S_OK : E_FAIL;
  1348. }
  1349.  
  1350. int wce_MulDiv(int nNumber, int nNumerator, int nDenominator)
  1351. {
  1352.     __int64 x;
  1353.  
  1354.     x = (__int64)nNumber * (__int64)nNumerator;
  1355.     x /= (__int64)nDenominator;
  1356.  
  1357.     return (int)x;
  1358. }
  1359.  
  1360. HRESULT wce_CreateStreamOnHGlobal(
  1361.     HGLOBAL     hGlobal,
  1362.     BOOL        fDeleteOnRelease,
  1363.     LPSTREAM *  ppstm)
  1364. {
  1365.     HRESULT             hr;
  1366.  
  1367.     *ppstm = new CStreamImp(
  1368.                     NULL,
  1369.                     NULL,
  1370.                     NULL,
  1371.                     NULL,  // pointer to Critical Section
  1372.                     &hr,
  1373.                     (PBYTE)hGlobal,
  1374.                     fDeleteOnRelease);
  1375.  
  1376.     if ((*ppstm == NULL) || (hr != S_OK))
  1377.     {
  1378.         if (*ppstm == NULL)
  1379.             return E_OUTOFMEMORY;
  1380.         else
  1381.             delete ppstm;
  1382.     }
  1383.  
  1384.     return hr;
  1385. }
  1386.  
  1387. } //namespace ATL
  1388.